package com.megalith.controller;

import cn.hutool.core.util.StrUtil;
import com.megalith.flowable.CustomProcessDiagramGenerator;
import com.megalith.service.impl.ProcessDiagramService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.util.IoUtil;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.image.impl.DefaultProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author lifp
 * @date 2025/06/08
 */
@Slf4j
@RestController
@Api(tags = "流程图")
@RequestMapping("diagram")
public class ProcessDiagramController {
    @Autowired
    private ProcessDiagramService diagramService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    //todo 根据businessKey（工单编号） 或  processInstanceId 或 act

    @GetMapping(value = "diagram-view")
    public void diagramView(String processInstanceId, HttpServletResponse httpServletResponse) {
        // 获得当前活动的节点
        String processDefinitionId;

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();


        String currentActivityId = null;
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceId)
                .active()
                .singleResult();
        if(task != null){
            Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).executionId(task.getExecutionId()).singleResult();
            currentActivityId = execution.getActivityId();
        }


        // 如果流程已经结束，则得到结束节点
        if (processInstance == null || processInstance.isEnded()) {
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        } else {
            // 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }
        List<String> highLightedActivities = new ArrayList<>();

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedActivityList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
        List<String> highLightedFlows = new ArrayList<>();

        for (HistoricActivityInstance tempActivity : highLightedActivityList) {
            String activityId = tempActivity.getActivityId();
            highLightedActivities.add(activityId);
            if("sequenceFlow".equals(tempActivity.getActivityType())){
                highLightedFlows.add(tempActivity.getActivityId());
            }
        }

        if(StrUtil.isNotEmpty(currentActivityId)){
            highLightedActivities.remove(currentActivityId);
            highLightedActivities.add(currentActivityId);
        }


        // 获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration engConf = processEngine.getProcessEngineConfiguration();

        //ProcessDiagramGenerator diagramGenerator = engConf.getProcessDiagramGenerator();
        ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivities, highLightedFlows, engConf.getActivityFontName(),
                engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int length;
        try {
            out = httpServletResponse.getOutputStream();
            while ((length = in.read(buf)) != -1) {
                out.write(buf, 0, length);
            }
        } catch (IOException e) {
            log.error("操作异常", e);
        } finally {
            IoUtil.closeSilently(out);
            IoUtil.closeSilently(in);
        }
    }

    private BpmnModel getBpmnModel(String processInstanceId) {
        ProcessDefinition processDefinition = getProcessDefinition(processInstanceId);
        return repositoryService.getBpmnModel(processDefinition.getId());
    }

    private ProcessDefinition getProcessDefinition(String processInstanceId) {
        // 先尝试获取运行中的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (processInstance != null) {
            return repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
        }

        // 如果流程已结束，从历史中获取
        HistoricProcessInstance historicInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();

        if (historicInstance == null) {
            throw new RuntimeException("Process instance not found: " + processInstanceId);
        }

        return repositoryService.getProcessDefinition(historicInstance.getProcessDefinitionId());
    }

    // 获取字体配置（支持中文）
    private String getActivityFontName() {
        return Optional.of(processEngine.getProcessEngineConfiguration().getActivityFontName()).orElse("Arial");
    }

    private String getLabelFontName() {
        return Optional.of(processEngine.getProcessEngineConfiguration().getLabelFontName()).orElse("Arial");
    }

    private String getAnnotationFontName() {
        return Optional.of(processEngine.getProcessEngineConfiguration().getAnnotationFontName()).orElse("Arial");
    }
}
